package com.kaikeba.estack.dao.imp;


import com.google.common.collect.ImmutableMap;
import com.kaikeba.estack.bean.Express;
import com.kaikeba.estack.common.jdbc.DataSourceUtil;
import com.kaikeba.estack.common.jdbc.JdbcUtil;
import com.kaikeba.estack.exception.DataAccessException;
import com.kaikeba.estack.common.util.BeanUtil;
import com.kaikeba.estack.dao.BaseExpressDao;
import com.kaikeba.estack.exception.DuplicateCodeException;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;

public class ExpressDaoMysql extends BaseDaoImpl<Express> implements BaseExpressDao {

    private static final String TABLE_NAME = "express";

    //用于查询数据库中的全部快递（总数+新增），待取件快递（总数+新增）
    public static final String SQL_CONSOLE = "select " +
            "count(id) data1_size," +
            "count(to_days(intime)=to_days(now()) or null) data1_day," +
            "count(status=0 or null) data2_size," +
            "count(to_days(intime)=to_days(now()) and status=0 or null) data2_day" +
            " from express";
    //用于分页查询数据库中的快递信息
    public static final String SQL_FIND_LIMIT = "select * from express limit :pageNumber,:offset";
    //通过快递单号查询快递信息
    public static final String SQL_FIND_BY_NUMBER = "select *  from express where number = :number and is_del = 0";
    //通过快递取件码，查询快递信息
    public static final String SQL_FIND_BY_CODE = "select *  from express where code = :code and is_del = 0";
    //通过用户手机号查询快递信息
    public static final String SQL_FIND_BY_USER_PHONE = "select * from express where user_phone = :userPhone and is_del = 0";
    //通过录入人手机号查询快递信息
    public static final String SQL_FIND_BY_SYS_PHONE = "select * from express where sys_phone = :sysPhone and is_del = 0";
    //录入快递
    public static final String SQL_INSERT = "insert into express (number,username,user_phone,company,code,in_time,status,sys_phone) values(:number,:username,:userPhone,:company,:code,now(),0,:sysPhone)";
    //快递修改
    public static final String SQL_UPDATE = "update express set number=:number,username=:username,company=:company,status=:status where id=:id";
    //快递的状态码改变（取件）
    public static final String SQL_UPDATE_STATUS = "update express set status=1,out_time=now(),code=null where code=:code";


    /**
     * 用于查询数据库中的全部快递（总数+新增），待取件快递（总数+新增）
     *
     * @return [{size:总数,day:新增},{size:总数,day:新增}]
     */
    @Override
    public List<Map<String, Object>> console() {
        try {
            return JdbcUtil.queryForListMap(DataSourceUtil.getConnection(), SQL_CONSOLE);
        } catch (SQLException sqlException) {
            throw new DataAccessException(sqlException);
        }
    }

    /**
     * 用于查询所有快递
     *
     * @param limit      是否分页的标记，true表示分页。false表示查询所有快递
     * @param offset     SQL语句的起始索引
     * @param pageNumber 页查询的数量
     * @return 快递的集合
     */
    @Override
    public List<Express> listAll(boolean limit, int offset, int pageNumber) {
        if (limit) {
            return super.list(SQL_FIND_LIMIT, ImmutableMap.of("offset", offset, "pageNumber", pageNumber));
        } else {
            return super.listAll();
        }
    }

    /**
     * 根据快递单号，查询快递信息
     *
     * @param number 单号
     * @return 查询的快递信息，单号不存在时返回null
     */
    @Override
    public Express findByNumber(String number) {
        return super.find(SQL_FIND_BY_NUMBER, ImmutableMap.of("number", number));
    }

    /**
     * 根据快递取件码，查询快递信息
     *
     * @param code 取件码
     * @return 查询的快递信息，取件码不存在时返回null
     */
    @Override
    public Express findByCode(String code) {
        return super.find(SQL_FIND_BY_CODE, ImmutableMap.of("code", code));
    }

    /**
     * 根据用户手机号码，查询他所有的快递信息
     *
     * @param userPhone 手机号码
     * @return 查询的快递信息列表
     */
    @Override
    public List<Express> findByUserPhone(String userPhone) {
        return super.list(SQL_FIND_BY_USER_PHONE, ImmutableMap.of("userPhone", userPhone));
    }

    /**
     * 根据录入人手机号码，查询录入的所有记录
     *
     * @param sysPhone 手机号码
     * @return 查询的快递信息列表
     */
    @Override
    public List<Express> findBySysPhone(String sysPhone) {
        return super.list(SQL_FIND_BY_SYS_PHONE, ImmutableMap.of("sysPhone", sysPhone));
    }

    /**
     * 快递的录入
     * INSERT INTO EXPRESS (NUMBER,USERNAME,USERPHONE,COMPANY,CODE,INTIME,STATUS,SYSPHONE) VALUES(?,?,?,?,?,NOW(),0,?)
     *
     * @param e 要录入的快递对象
     * @return 录入的结果，true表示成功，false表示失败
     */
    @Override
    public boolean insert(Express e) throws DuplicateCodeException {
        try {
            super.insert(SQL_INSERT, BeanUtil.convert(e, Map.class));
        } catch (DataAccessException e1) {
            if (e1.getMessage().endsWith("for key 'code'")) {
                //是因为取件码重复,而出现了异常
                DuplicateCodeException e2 = new DuplicateCodeException(e1.getMessage());
                throw e2;
            } else {
                throw e1;
            }
        }
        return false;
    }

    /**
     * 快递的修改
     * UPDATE EXPRESS SET NUMBER=?,USERNAME=?,COMPANY=?,STATUS=? WHERE ID=?
     *
     * @param newExpress 新的快递对象（number，company,username,userPhone）
     * @return 修改的结果，true表示成功，false表示失败
     */
    @Override
    public boolean update(Express newExpress) {
        return super.update(SQL_UPDATE, BeanUtil.convert(newExpress, Map.class));
    }

    /**
     * 更改快递的状态为1，表示取件完成
     *
     * @param code 要修改的快递单号
     * @return 修改的结果，true表示成功，false表示失败
     */
    @Override
    public boolean updateStatus(String code) {
        return super.update(SQL_UPDATE_STATUS, ImmutableMap.of("code", code));
    }

    @Override
    public String getTableName() {
        return TABLE_NAME;
    }
}
